﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;

namespace Pixysoft.Framework.Reflection.testdriven
{
    class Class_aop
    {
        public void test000()
        {
            AADynamicProxy proxy = new AADynamicProxy();
            IAA obj = (IAA)proxy.GetTransparentProxy();
            Console.WriteLine(obj.Name);
        }

        //测试 attribute, realproxy, dynamicproxy 的性能
        public void test001()
        {
            //------ Test started: Assembly: Pixysoft.Framework.Reflection.dll ------

            //aop
            //    Time Elapsed:		952ms
            //    CPU time:		921,875,000ns
            //    Gen 0: 			72
            //    Gen 1: 			0
            //    Gen 2: 			0

            //dynamic
            //    Time Elapsed:		117ms
            //    CPU time:		125,000,000ns
            //    Gen 0: 			13
            //    Gen 1: 			0
            //    Gen 2: 			0

            //real
            //    Time Elapsed:		68ms
            //    CPU time:		62,500,000ns
            //    Gen 0: 			8
            //    Gen 1: 			0
            //    Gen 2: 			0


            //1 passed, 0 failed, 0 skipped, took 1.22 seconds (Ad hoc).


            Pixysoft.Tools.CodeTimer.Initialize();

            Pixysoft.Tools.CodeTimer.Time("aop", 10000, delegate()
            {
                Aop aa = new Aop();
                aa.Name = 13;
            });

            Pixysoft.Tools.CodeTimer.Time("real", 10000, delegate()
            {
                IAA iaa = (IAA)new AARealproxy().GetTransparentProxy();
                iaa.Name = 13;
            });


            Pixysoft.Tools.CodeTimer.Time("dynamic", 10000, delegate()
            {
                IAA iaa = (IAA)new AADynamicProxy().GetTransparentProxy();
                iaa.Name = 13;
            });

        }

        //测试realproxy / dynamicproxy的差别
        public void test002()
        {
            //            dynamic
            //    Time Elapsed:		142ms ->82ms -> 56ms 
            //    CPU time:		109,375,000ns
            //    Gen 0: 			24
            //    Gen 1: 			0
            //    Gen 2: 			0

            //real
            //    Time Elapsed:		70ms
            //    CPU time:		78,125,000ns
            //    Gen 0: 			7
            //    Gen 1: 			0
            //    Gen 2: 			0

            Pixysoft.Tools.CodeTimer.Initialize();

            Pixysoft.Tools.CodeTimer.Time("dynamic", 10000, delegate()
            {
                IAA iaa = (IAA)new AADynamicProxy().GetTransparentProxy();
                iaa.Name = 13;

            });

            Pixysoft.Tools.CodeTimer.Time("real", 10000, delegate()
            {
                IAA iaa = (IAA)new AARealproxy().GetTransparentProxy();
                iaa.Name = 13;
            });
        }

        // realproxy vs dynamicproxy::overall
        public void test003()
        {
            object value2 = default(double);

            Console.WriteLine(value2.GetType().Name);

            //            times:10000
            //dynamic
            //    Time Elapsed:		89ms ->74ms 不使用parse，直接返回message的结果
            //    CPU time:		93,750,000ns
            //    Gen 0: 			9
            //    Gen 1: 			0
            //    Gen 2: 			0

            //real
            //    Time Elapsed:		125ms
            //    CPU time:		109,375,000ns
            //    Gen 0: 			14
            //    Gen 1: 			0
            //    Gen 2: 			0

            Pixysoft.Tools.CodeTimer.Initialize();

            Pixysoft.Tools.CodeTimer.Time("dynamic", 10000, delegate()
            {
                IAA iaa = (IAA)new AADynamicProxy().GetTransparentProxy();
                iaa.Name = 13;
                object value = iaa.Name;
            });

            Pixysoft.Tools.CodeTimer.Time("real", 10000, delegate()
            {
                IAA iaa = (IAA)new AARealproxy().GetTransparentProxy();
                iaa.Name = 13;
                object value = iaa.Name;
            });
        }
    }

    class AADynamicProxy : DynamicProxy
    {
        public AADynamicProxy()
            : base(typeof(IAA))
        {
        }

        public override IDynamicMethodReturnMessage Invoke(IDynamicMethodCallMessage msg)
        {
            return base.SyncProcessMessage(msg);
        }
    }

    class AARealproxy : RealProxy
    {
        public AARealproxy()
            : base(typeof(IAA))
        {
        }

        public override IMessage Invoke(IMessage msg)
        {
            return new ReturnMessage(0, null, 0, null, msg as IMethodCallMessage);
        }
    }

    public interface IAA : ICloneable
    {
        int Name { get;set;}
    }










    [OrmInterceptor]
    public class Aop : ContextBoundObject, IDisposable
    {
        public void Dispose()
        {

        }

        public int Name { get { return 0; } set { } }
    }

    [AttributeUsage(AttributeTargets.Class)]
    internal class OrmInterceptorAttribute : ContextAttribute
    {
        public OrmInterceptorAttribute() : base("OrmInterceptor") { }

        public override void GetPropertiesForNewContext(IConstructionCallMessage ccm)
        {
            //在这里拦截了构造函数

            ccm.ContextProperties.Add(new OrmInterceptorProperty());
        }
    }

    internal class OrmInterceptorProperty : IContextProperty, IContributeObjectSink
    {
        public IMessageSink GetObjectSink(MarshalByRefObject o, IMessageSink next)
        {
            if (o == null)
                throw new Exception("object o is null.");

            return new OrmDummyAspect(next);
        }

        public void Freeze(Context newContext)
        {

        }

        public bool IsNewContextOK(Context newCtx)
        {
            return true;
        }

        public string Name
        {
            get { return "ORMInterceptorProperty"; }
        }
    }

    class OrmDummyAspect : IMessageSink
    {
        internal OrmDummyAspect(IMessageSink next)
        {
            m_next = next;
        }

        private IMessageSink m_next;

        public IMessageSink NextSink
        {
            get { return m_next; }
        }

        public IMessage SyncProcessMessage(IMessage msg)
        {
            return m_next.SyncProcessMessage(msg);
        }

        public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
        {
            throw new InvalidOperationException();
        }
    }

}

